package com.zhihaoliang.animationtrain.animator

import android.animation.Animator
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Canvas
import android.graphics.RadialGradient
import android.graphics.Shader
import android.graphics.drawable.ShapeDrawable
import android.graphics.drawable.shapes.OvalShape
import android.os.Bundle
import android.view.View
import android.view.animation.AccelerateInterpolator
import androidx.appcompat.app.AppCompatActivity
import com.zhihaoliang.animationtrain.annotation.Info
import com.zhihaoliang.animationtrain.databinding.AnimatorEventsActivityBinding
import com.zhihaoliang.animationtrain.util.ShapeHolder

@Info("属性动画的控制", "介绍属性动画的控制，包括cancel和end")
class AnimatorEventsActivity : AppCompatActivity() {

    private lateinit var mBinding: AnimatorEventsActivityBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        mBinding = AnimatorEventsActivityBinding.inflate(layoutInflater).apply {
            setContentView(root)
        }

        val animView = MyAnimationView(this)
        mBinding.animatorContainer.addView(animView)

        initView()
        mBinding.animatorBtnStart.setOnClickListener {
            animView.startAnimation(mBinding.animatorCbEnd.isChecked)
        }
        mBinding.animatorBtnCancel.setOnClickListener {
            animView.cancleAnimation()
        }

        mBinding.animatorBtnEnd.setOnClickListener {
            animView.endAnimation()
        }
    }

    private fun initView() {
        mBinding.animatorTvStart.alpha = 0.5F
        mBinding.animatorTvRepeat.alpha = 0.5F
        mBinding.animatorTvCancel.alpha = 0.5F
        mBinding.animatorTvEnd.alpha = 0.5F

        mBinding.animatorTvStartState.alpha = 0.5F
        mBinding.animatorTvRepeatState.alpha = 0.5F
        mBinding.animatorTvCancelState.alpha = 0.5F
        mBinding.animatorTvEndState.alpha = 0.5F
    }

    private inner class MyAnimationView(context: Context) : View(context),
        Animator.AnimatorListener,
        ValueAnimator.AnimatorUpdateListener {

        private val ball = createBall()

        private var endImmediately = false

        private var animation: AnimatorSet? = null

        override fun onAnimationRepeat(animation: Animator) {
            if (animation is AnimatorSet) {
                mBinding.animatorTvRepeat.alpha = 1F
            } else {
                mBinding.animatorTvRepeatState.alpha = 1F
            }
        }

        override fun onAnimationEnd(animation: Animator) {
            if (animation is AnimatorSet) {
                mBinding.animatorTvEnd.alpha = 1F
            } else {
                mBinding.animatorTvEndState.alpha = 1F
            }
        }

        override fun onAnimationCancel(animation: Animator) {
            if (animation is AnimatorSet) {
                mBinding.animatorTvCancel.alpha = 1F
            } else {
                mBinding.animatorTvCancelState.alpha = 1F
            }
        }

        override fun onAnimationStart(animation: Animator) {
            if (animation is AnimatorSet) {
                mBinding.animatorTvStart.alpha = 1F
            } else {
                mBinding.animatorTvStartState.alpha = 1F
            }

            if (endImmediately) {
                animation.end()
            }
        }

        override fun onAnimationUpdate(animation: ValueAnimator) {
            invalidate()
        }

        fun startAnimation(endImmediately: Boolean) {
            this.endImmediately = endImmediately

            initView()

            createAnimation()

            animation!!.start()
        }

        fun cancleAnimation() {
            createAnimation()
            animation!!.cancel()
        }

        fun endAnimation() {
            createAnimation()
            animation!!.end()
        }

        override fun onDraw(canvas: Canvas) {
            canvas.save()
            canvas.translate(ball.x, ball.y)
            ball.shapeDrawable.draw(canvas)
            canvas.restore()
        }

        private fun createAnimation() {
            if (animation == null) {
                val yAnim = ObjectAnimator.ofFloat(
                    ball, "y",
                    ball.y, height - 50f
                ).setDuration(1500)
                yAnim.repeatCount = 0
                yAnim.repeatMode = ValueAnimator.REVERSE
                yAnim.interpolator = AccelerateInterpolator(2f)
                yAnim.addUpdateListener(this)
                yAnim.addListener(this)

                val xAnim: ObjectAnimator = ObjectAnimator.ofFloat(
                    ball, "x",
                    ball.x, ball.x + 300
                ).setDuration(1000)
                xAnim.startDelay = 0
                xAnim.repeatCount = 0
                xAnim.repeatMode = ValueAnimator.REVERSE
                xAnim.interpolator = AccelerateInterpolator(2f)

                val alphaAnim =
                    ObjectAnimator.ofFloat(ball, "alpha", 1f, .5f).setDuration(1000)
                val alphaSeq = AnimatorSet()
                alphaSeq.play(alphaAnim)

                animation = AnimatorSet()
                animation!!.playTogether(yAnim, xAnim)
                animation!!.addListener(this)
            }
        }

        private fun createBall(): ShapeHolder {
            val circle = OvalShape()
            circle.resize(50f, 50f)
            val drawable = ShapeDrawable(circle)
            val shapeHolder = ShapeHolder(drawable)
            shapeHolder.x = 0F
            shapeHolder.y = 0F
            val red = (Math.random() * 255).toInt()
            val green = (Math.random() * 255).toInt()
            val blue = (Math.random() * 255).toInt()
            val color = -0x1000000 or (red shl 16) or (green shl 8) or blue
            val paint =
                drawable.paint //new Paint(Paint.ANTI_ALIAS_FLAG);
            val darkColor = -0x1000000 or (red / 4 shl 16) or (green / 4 shl 8) or blue / 4
            val gradient = RadialGradient(
                37.5f, 12.5f,
                50f, color, darkColor, Shader.TileMode.CLAMP
            )
            paint.shader = gradient
            shapeHolder.paint = paint
            return shapeHolder
        }

    }
}
